package org.springblade.modules.admin.service.impl;

import lombok.extern.slf4j.Slf4j;
import org.dromara.easyes.core.conditions.select.LambdaEsQueryWrapper;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tenant.annotation.TenantIgnore;
import org.springblade.core.tool.utils.Func;
import org.springblade.modules.admin.dto.es.SearchParamDTO;
import org.springblade.modules.admin.entity.es.ProjectDocument;
import org.springblade.modules.admin.mapper.es.ProjectDocumentMapper;
import org.springblade.modules.admin.service.BuildingService;
import org.springblade.modules.admin.service.IEsProjectSearchService;
import org.springblade.modules.admin.vo.BuildingESVO;
import org.springblade.modules.auth.utils.TokenUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@Service
@Slf4j
public class EsProjectSearchServiceImpl implements IEsProjectSearchService {

	@Autowired
	private ProjectDocumentMapper projectDocumentMapper;
	@Autowired
	private BuildingService buildingService;

	@Override
	@TenantIgnore
	public void init() {
		List<ProjectDocument> projectData = new ArrayList<>();
		List<BuildingESVO> list = buildingService.listForEsInit();
		for (int i = 0; i < list.size(); i++) {
			BuildingESVO building = list.get(i);
			ProjectDocument document = new ProjectDocument();
			document.setId(building.getId());
			document.setName(building.getName());
			document.setNamePinyin(building.getName());
			document.setProvinceCode(building.getProvinceCode());
			document.setCityCode(building.getCityCode());
			document.setAdCode(building.getAdCode());
			document.setTenantId(building.getTenantId());
			document.setAlias(building.getAlias());
			document.setAliasPinyin(building.getAliasPinyin());
			projectData.add(document);
		}
		projectDocumentMapper.insertBatch(projectData);
		log.info("执行完毕,请通过ES工具查看初始化结果");
	}

	@Override
	public List<ProjectDocument> listDocumentByTitle(SearchParamDTO searchParam) {
		LambdaEsQueryWrapper<ProjectDocument> wrapper = new LambdaEsQueryWrapper<>();
		//目前采用自定义分词器的方式,先用ik分词器分词,然后是用pinyin分词器对ik分词后的结果单独进行分词,目前这种效果最佳
		if (Func.isNotBlank(searchParam.getSearchKey())) {
			Pattern p = Pattern.compile("[\\u4e00-\\u9fa5]");
			Matcher m = p.matcher(searchParam.getSearchKey());
			if (m.find()) {
				// 含有中文
				wrapper.and(t -> t.matchPhrase(ProjectDocument::getName, searchParam.getSearchKey()).or()
					.matchPhrase(ProjectDocument::getAlias, searchParam.getSearchKey()));
			} else {
				// 拼音
				wrapper.and(t -> t.matchPhrase(ProjectDocument::getNamePinyin, searchParam.getSearchKey()).or()
					.matchPhrase(ProjectDocument::getAliasPinyin, searchParam.getSearchKey()));
			}
		}

		if (Func.isNotBlank(searchParam.getTenantId())) {
			wrapper.eq(ProjectDocument::getTenantId, searchParam.getTenantId());
		}
		if (Func.isNotBlank(searchParam.getProvinceCode())) {
			wrapper.eq(ProjectDocument::getProvinceCode, searchParam.getProvinceCode());
		}
		if (Func.isNotBlank(searchParam.getCityCode())) {
			wrapper.eq(ProjectDocument::getCityCode, searchParam.getCityCode());
		}
		if (Func.isNotBlank(searchParam.getAdCode())) {
			wrapper.eq(ProjectDocument::getAdCode, searchParam.getAdCode());
		}
		List<ProjectDocument> projectDocuments = projectDocumentMapper.selectList(wrapper);
		if (Func.isEmpty(projectDocuments)) {
			return projectDocuments;
		}

		// 去掉未命中的别名高亮内容
		if (Func.isNotEmpty(projectDocuments) && Func.isNotBlank(searchParam.getSearchKey())) {
			for (ProjectDocument projectDocument : projectDocuments) {
				String aliasHighlightContent = projectDocument.getAliasHighlightContent();
				if (Func.isBlank(aliasHighlightContent)) {
					continue;
				}
				List<String> aliasList = Func.toStrList(",", aliasHighlightContent).stream().filter(t -> t.contains("<em>")).collect(Collectors.toList());
				projectDocument.setAliasHighlightContent(aliasList.stream().collect(Collectors.joining(",")));
			}
		}

		/**
		 * 排序规则：
		 * 关键字直接匹配，优先级最高,否则，则根据命中位置越前，优先级越高。
		 */
		projectDocuments = projectDocuments.stream().sorted(Comparator.comparingInt(t -> {
			// 默认权重值
			int score = 500;
			int nameScore = t.getName().toLowerCase().indexOf(searchParam.getSearchKey());
			if (nameScore >= 0) {
				score = nameScore;
			}

			if (Func.isNotBlank(t.getAlias())) {
				int aliasScore = t.getAlias().toLowerCase().indexOf(searchParam.getSearchKey());
				if (aliasScore >= 0 && aliasScore < score) {
					score = aliasScore;
				}
			}

			if (score == 500) {
				if (Func.isNotBlank(t.getHighlightContent())) {
					int lightNameScore = t.getHighlightContent().indexOf("<em>");
					if (lightNameScore >= 0 && lightNameScore < score) {
						// 为了避免高于关键字直接匹配优先级，这里权重值+100
						score = lightNameScore + 100;
					}
				}

				if (Func.isNotBlank(t.getAliasHighlightContent())) {
					int lightAliasScore = t.getAliasHighlightContent().indexOf("<em>");
					if (lightAliasScore >= 0 && lightAliasScore < score) {
						// 为了避免高于关键字直接匹配优先级，这里权重值+100
						score = lightAliasScore + 100;
					}
				}
			}

			return score;
		})).collect(Collectors.toList());

		return projectDocuments;
	}
}
